#ifndef __MISC_H__
#define __MISC_H__

#include "types.h"

/* symbolic CSR names: */
#define CSR_CYCLE		0xc00
#define CSR_TIME		0xc01
#define CSR_INSTRET		0xc02
#define CSR_CYCLEH		0xc80
#define CSR_TIMEH		0xc81
#define CSR_INSTRETH		0xc82

#define CSR_SSTATUS		0x100
#define CSR_SIE			0x104
#define CSR_STVEC		0x105
#define CSR_SCOUNTEREN		0x106
#define CSR_SSCRATCH		0x140
#define CSR_SEPC		0x141
#define CSR_SCAUSE		0x142
#define CSR_STVAL		0x143
#define CSR_SIP			0x144
#define CSR_SATP		0x180

#define CSR_VSSTATUS		0x200
#define CSR_VSIE		0x204
#define CSR_VSTVEC		0x205
#define CSR_VSSCRATCH		0x240
#define CSR_VSEPC		0x241
#define CSR_VSCAUSE		0x242
#define CSR_VSTVAL		0x243
#define CSR_VSIP		0x244
#define CSR_VSATP		0x280

#define CSR_HSTATUS		0x600
#define CSR_HEDELEG		0x602
#define CSR_HIDELEG		0x603
#define CSR_HIE			0x604
#define CSR_HTIMEDELTA		0x605
#define CSR_HCOUNTEREN		0x606
#define CSR_HGEIE		0x607
#define CSR_HTIMEDELTAH		0x615
#define CSR_HTVAL		0x643
#define CSR_HIP			0x644
#define CSR_HVIP		0x645
#define CSR_HTINST		0x64a
#define CSR_HGATP		0x680
#define CSR_HGEIP		0xe12

#define CSR_MSTATUS		0x300
#define CSR_MISA		0x301
#define CSR_MIE			0x304
#define CSR_MTVEC		0x305
#define CSR_MSCRATCH		0x340
#define CSR_MEPC		0x341
#define CSR_MCAUSE		0x342
#define CSR_MTVAL		0x343
#define CSR_MIP			0x344
#define CSR_PMPCFG0		0x3a0
#define CSR_PMPADDR0		0x3b0
#define CSR_MVENDORID		0xf11
#define CSR_MARCHID		0xf12
#define CSR_MIMPID		0xf13
#define CSR_MHARTID		0xf14

#define XSTR(x)                 #x
#define __STR(s)                #s
#define STRINGIFY(s)            __STR(s)

/**
 * \brief CSR operation Macro for csrr instruction.
 * \details
 * Read the content of csr register to __v and return it
 * \param csr   CSR macro definition defined in
 *              \ref NMSIS_Core_CSR_Registers, eg. \ref CSR_MSTATUS
 * \return the CSR register value
 */
#define __RV_CSR_READ(csr)                                      \
    ({                                                          \
        register rv_csr_t __v;                                  \
        asm volatile("csrr %0, " STRINGIFY(csr)               \
                     : "=r"(__v)                                \
                     :                                          \
                     : "memory");                               \
        __v;                                                    \
    })

#if 0
// linux
#define csr_read(csr)						\
({								\
	register unsigned long __v;				\
	__asm__ __volatile__ ("csrr %0, " __ASM_STR(csr)	\
			      : "=r" (__v) :			\
			      : "memory");			\
	__v;							\
})

#endif
/**
 * \defgroup NMSIS_Core_Registers     Register Define and Type Definitions
 * \brief   Type definitions and defines for core registers.
 *
 * @{
 */
#ifndef __RISCV_XLEN
  /** \brief Refer to the width of an integer register in bits(either 32 or 64) */
  #ifndef __riscv_xlen
    #define __RISCV_XLEN    32
  #else
    #define __RISCV_XLEN    __riscv_xlen
  #endif
#endif /* __RISCV_XLEN */

/** \brief Type of Control and Status Register(CSR), depends on the XLEN defined in RISC-V */
#if __RISCV_XLEN == 32
  typedef uint32_t rv_csr_t;
#elif __RISCV_XLEN == 64
  typedef uint64_t rv_csr_t;
#else
  typedef uint32_t rv_csr_t;
#endif
/** @} */ /* End of Doxygen Group NMSIS_Core_Registers */
/**
 * \defgroup NMSIS_Core_Base_Registers     Base Register Define and Type Definitions
 * \ingroup NMSIS_Core_Registers
 * \brief   Type definitions and defines for base core registers.
 *
 * @{
 */
/**
 * \brief  Union type to access MISA register.
 */
typedef union {
    struct {
        rv_csr_t a:1;                           /*!< bit:     0  Atomic extension */
        rv_csr_t b:1;                           /*!< bit:     1  Tentatively reserved for Bit-Manipulation extension */
        rv_csr_t c:1;                           /*!< bit:     2  Compressed extension */
        rv_csr_t d:1;                           /*!< bit:     3  Double-precision floating-point extension */
        rv_csr_t e:1;                           /*!< bit:     4  RV32E base ISA */
        rv_csr_t f:1;                           /*!< bit:     5  Single-precision floating-point extension */
        rv_csr_t g:1;                           /*!< bit:     6  Additional standard extensions present */
        rv_csr_t h:1;                           /*!< bit:     7  Hypervisor extension */
        rv_csr_t i:1;                           /*!< bit:     8  RV32I/64I/128I base ISA */
        rv_csr_t j:1;                           /*!< bit:     9  Tentatively reserved for Dynamically Translated Languages extension */
        rv_csr_t _reserved1:1;                  /*!< bit:     10 Reserved  */
        rv_csr_t l:1;                           /*!< bit:     11 Tentatively reserved for Decimal Floating-Point extension  */
        rv_csr_t m:1;                           /*!< bit:     12 Integer Multiply/Divide extension */
        rv_csr_t n:1;                           /*!< bit:     13 User-level interrupts supported  */
        rv_csr_t _reserved2:1;                  /*!< bit:     14 Reserved  */
        rv_csr_t p:1;                           /*!< bit:     15 Tentatively reserved for Packed-SIMD extension  */
        rv_csr_t q:1;                           /*!< bit:     16 Quad-precision floating-point extension  */
        rv_csr_t _resreved3:1;                  /*!< bit:     17 Reserved  */
        rv_csr_t s:1;                           /*!< bit:     18 Supervisor mode implemented  */
        rv_csr_t t:1;                           /*!< bit:     19 Tentatively reserved for Transactional Memory extension  */
        rv_csr_t u:1;                           /*!< bit:     20 User mode implemented  */
        rv_csr_t v:1;                           /*!< bit:     21 Tentatively reserved for Vector extension  */
        rv_csr_t _reserved4:1;                  /*!< bit:     22 Reserved  */
        rv_csr_t x:1;                           /*!< bit:     23 Non-standard extensions present  */
#if defined(__RISCV_XLEN) && __RISCV_XLEN == 64
        rv_csr_t _reserved5:38;                 /*!< bit:     24..61 Reserved  */
        rv_csr_t mxl:2;                         /*!< bit:     62..63 Machine XLEN  */
#else
        rv_csr_t _reserved5:6;                  /*!< bit:     24..29 Reserved  */
        rv_csr_t mxl:2;                         /*!< bit:     30..31 Machine XLEN  */
#endif
    } b;                                        /*!< Structure used for bit  access */
    rv_csr_t d;                                 /*!< Type      used for csr data access */
} CSR_MISA_Type;

void print_misa(void);

#endif
